using System;
using System.Collections;
using System.Web;
using System.Xml;

namespace Deepcode.Flux.Core.Services.Configuration
{
	/// <summary>
	/// PropertyFile provides simple access to a .config file. Simple .config files
	/// are XML files with a single level of xml data. In other words, there is the main
	/// document root element, and it's children. There are no further nested elements and
	/// each child within the root is uniquely named.
	/// </summary>
	public class PropertyFile
	{
		/// <summary>
		/// Holds the full path and filename to the configuration file
		/// </summary>
		protected string CfgFile = null;
		/// <summary>
		/// Property allowing subclasses to get/set the filename
		/// </summary>
		protected virtual string FileName
		{
			get
			{
				return CfgFile;
			}
			set
			{
				CfgFile = value;
			}
		}
		/// <summary>
		/// Returns FileName (a relative path ie: ~/Settings/MyApp.config)
		/// as a mapped path. IE: C:\wwwroot\site\settings\myapp.config
		/// </summary>
		protected virtual string ResolveFileName
		{
			get
			{
				return HttpContext.Current.Server.MapPath(FileName);
			}
		}
		/// <summary>
		/// Holds the hashtable of properties to be serialised.
		/// </summary>
		protected Hashtable Properties = new Hashtable();
		/// <summary>
		/// Provides access to a property by it's key. 
		/// </summary>
		public string this[ string key ]
		{
			get
			{
				string item = (string) Properties[key];
				if( item == null ) return String.Empty;
				return item;
			}
			set
			{
				Properties[key] = value;
			}
		}
		/// <summary>
		/// Implements a default property file constructor. This is
		/// only available to subclasses of PropertyFile, such as
		/// the BaseCachedConfigurationFile.
		/// </summary>
		protected PropertyFile()
		{
			if( System.IO.File.Exists( ResolveFileName ))
				LoadPropertyFile();
		}
		/// <summary>
		/// Construct a property file object, specifying it's configuration file location.
		/// If the file exists at construction time, it is loaded into this instance.
		/// </summary>
		/// <param name="ConfigurationFile"></param>
		public PropertyFile( string ConfigurationFile )
		{
			FileName = ConfigurationFile;
			if( System.IO.File.Exists( ResolveFileName ))
				LoadPropertyFile();
		}
		/// <summary>
		/// Method used by the constructor to load the XML file.
		/// </summary>
		protected virtual void LoadPropertyFile()
		{
			XmlDocument doc = new XmlDocument();
			doc.Load( ResolveFileName );

			foreach( object o in doc.DocumentElement.ChildNodes )
			{
				if( o is XmlElement )
				{
					XmlElement el = (XmlElement) o;
					this[el.Name] = el.InnerText;
				}
			}
		}
		/// <summary>
		/// Saves the .config file to the filename specified in the constructor.
		/// </summary>
		public void Save()
		{
			XmlDocument doc = new XmlDocument();
			XmlElement props = doc.CreateElement("Properties");
			doc.AppendChild( props );

			foreach( DictionaryEntry e in this.Properties )
			{
				XmlElement prop = doc.CreateElement( (string) e.Key );
				prop.InnerText = (string) e.Value;
				props.AppendChild( prop );
			}
			doc.Save( ResolveFileName );
		}
	}
}
